package repository

import (
	"gorm.io/gorm"
	"shop-common/utils/queryWrapper"
	"shop-sys/model"
	"shop-sys/pkg/constant"
	"shop-sys/pkg/vo"
)

type ISysMenuRepository interface {
	FindOne(*gorm.DB, *queryWrapper.WherePair) (*model.SysMenu, error)
	FindListMenu(*gorm.DB) ([]*model.SysMenu, error)
	FindListMenuByUserId(*gorm.DB, uint) ([]*model.SysMenu, error)
	FindListMenuAndBtn(*gorm.DB) ([]*model.SysMenu, error)
	FindListSimpleMenuNoButton(*gorm.DB) ([]*vo.SimpleMenuVO, error)
	FindListRootMenu(*gorm.DB) ([]*vo.SimpleMenuVO, error)
	FindListChildrenMenuByParentId(*gorm.DB, uint) ([]*vo.SimpleMenuVO, error)
	FindById(*gorm.DB, uint) (*model.SysMenu, error)
	Create(*gorm.DB, *model.SysMenu) (*model.SysMenu, error)
	Updates(*gorm.DB, uint, map[string]interface{}) error
	Delete(*gorm.DB, uint) error
}

type sysMenuRepository struct{}

func NewSysMenuRepository() ISysMenuRepository {
	return &sysMenuRepository{}
}

func (m *sysMenuRepository) FindOne(db *gorm.DB, wp *queryWrapper.WherePair) (sysMenu *model.SysMenu, err error) {
	return sysMenu, db.Model(&sysMenu).Where(wp.Query, wp.Args...).First(&sysMenu).Error
}

/**
 * 获取系统的所有菜单
 * @return 系统的所有菜单
 */
func (m *sysMenuRepository) FindListMenu(db *gorm.DB) (sysMenu []*model.SysMenu, err error) {
	return sysMenu, db.Model(&sysMenu).Where("type != ?", constant.MenuType_BUTTON).Order("order_num").Find(&sysMenu).Error
}

/**
 * 查询用户的所有菜单ID
 * @param userId 用户id
 * @return 该用户所有可用的菜单
 */
func (m *sysMenuRepository) FindListMenuByUserId(db *gorm.DB, userId uint) (list []*model.SysMenu, err error) {
	rows, err := db.Raw(`
		SELECT DISTINCT
			m.menu_id AS menu_id,
			m.parent_id,
			m.NAME,
			url,
			m.type,
			m.icon,
			m.order_num 
		FROM
			tz_sys_user_role ur
			LEFT JOIN tz_sys_role_menu rm ON ur.role_id = rm.role_id
			LEFT JOIN tz_sys_menu m ON m.menu_id = rm.menu_id 
		WHERE
			ur.user_id = ? and m.type != ? order by order_num
		`, userId, constant.MenuType_BUTTON).Rows()

	if err != nil {
		return
	}

	for rows.Next() {
		item := model.SysMenu{}
		err = rows.Scan(
			&item.MenuId,
			&item.ParentId,
			&item.Name,
			&item.Url,
			&item.Type,
			&item.Icon,
			&item.OrderNum,
		)
		if err != nil {
			return
		} else {
			list = append(list, &item)
		}
	}
	return
}

func (m *sysMenuRepository) FindListMenuAndBtn(db *gorm.DB) (sysMenu []*model.SysMenu, err error) {
	return sysMenu, db.Model(model.SysMenu{}).Order("order_num").Find(&sysMenu).Error
}

func (m *sysMenuRepository) Create(db *gorm.DB, sysMenu *model.SysMenu) (*model.SysMenu, error) {
	return sysMenu, db.Create(&sysMenu).Error
}

func (m *sysMenuRepository) FindListSimpleMenuNoButton(db *gorm.DB) (simpleMenu []*vo.SimpleMenuVO, err error) {
	err = db.Model(&model.SysMenu{}).
		Select([]string{"menu_id", "parent_id", "name"}).
		Where(" `type` != ?", constant.MenuType_BUTTON).
		Order("order_num desc").
		Find(&simpleMenu).Error
	return
}

func (m *sysMenuRepository) FindListRootMenu(db *gorm.DB) (simpleMenu []*vo.SimpleMenuVO, err error) {
	return simpleMenu, db.Model(&model.SysMenu{}).Select([]string{"menu_id", "name"}).Where("type = ?", constant.MenuType_CATALOG).Find(&simpleMenu).Error
}

func (m *sysMenuRepository) FindListChildrenMenuByParentId(db *gorm.DB, parentId uint) (simpleMenu []*vo.SimpleMenuVO, err error) {
	return simpleMenu, db.Model(&model.SysMenu{}).Select([]string{"menu_id", "name"}).Where("parent_id = ?", parentId).Find(&simpleMenu).Error
}

func (m *sysMenuRepository) FindById(db *gorm.DB, menuId uint) (sysMenu *model.SysMenu, err error) {
	return sysMenu, db.Model(&model.SysMenu{}).First(&sysMenu, menuId).Error
}

func (m *sysMenuRepository) Delete(db *gorm.DB, menuId uint) error {
	return db.Delete(&model.SysMenu{}, menuId).Error
}

func (m *sysMenuRepository) Updates(db *gorm.DB, menuId uint, columns map[string]interface{}) error {
	return db.Model(&model.SysMenu{}).Where("menu_id = ?", menuId).Updates(columns).Error
}
